package com.osell.selection.data.network;

import android.text.TextUtils;

import com.da.lon.wang.xlg.BuildConfig;
import com.da.lon.wang.xlg.MyApplication;
import com.google.gson.GsonBuilder;
import com.osell.selection.Constants;
import com.osell.selection.util.DeviceUuidFactory;
import com.osell.selection.util.MD5Utils;
import com.osell.selection.util.StorageUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import timber.log.Timber;

public class RestAPI {

    private static final String API_URL = BuildConfig.API_URL;

    private static final int DISK_CACHE_SIZE = 20 * 1024 * 1024; // 20MB
    private static RestAPI instance;
    private Retrofit retrofit;
    private OSellService oSellService;

    public static RestAPI getInstance() {
        if (instance == null) {
            synchronized (RestAPI.class) {
                if (instance == null) {
                    instance = new RestAPI();
                }
            }
        }
        return instance;
    }

    private static String bodyToString(RequestBody request) {
        try {
            Buffer buffer = new Buffer();
            request.writeTo(buffer);
            return buffer.readUtf8();
        } catch (IOException e) {
            return "";
        }
    }

    private Retrofit getRetrofit() {
        if (retrofit == null) {
            OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
                    .connectTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .cache(getCache());

            clientBuilder.interceptors().add(chain -> {
                List<String> pathSegments = chain.request().url().pathSegments();
                String lastPathSegment = pathSegments.get(pathSegments.size() - 1);
                String[] ar = lastPathSegment.split("-");
                String deviceId = new DeviceUuidFactory(MyApplication.getInstance()).getDeviceUuid().toString();
                String token = MD5Utils.getMD532(ar[0] + Constants.SECRET + (ar.length > 1 ? ar[1] : ""));
                String sign = MD5Utils.getMD532(Constants.SECRET_SIGN + deviceId + Constants.SECRET_SIGN);
                String language = MyApplication.getInstance().getResources().getConfiguration().locale.getLanguage();
                if (TextUtils.equals("zh", language)) {
                    language = "cn";
                }

                Request request = chain.request();
                RequestBody requestBody = request.body();
                String postBodyString = requestBody == null ? "" : bodyToString(requestBody);
                postBodyString += ((postBodyString.length() > 0) ? "&" : "") +
                        bodyToString(new FormBody.Builder()
                                .add("sign", sign)
                                .add("token", token)
                                .add("deviceId", deviceId)
                                .add("deviceType", "1")
                                .add("device_id", deviceId)
                                .add("device_type", "1")
                                .add("lan", language)
                                .build());
                return chain.proceed(request.newBuilder()
                        .method(request.method(), RequestBody.create(requestBody.contentType(), postBodyString))
                        .build());
            });
            if (BuildConfig.DEBUG) {
                clientBuilder.interceptors().add(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
            }
            retrofit = new Retrofit.Builder()
                    .baseUrl(API_URL)
                    .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().setDateFormat("MMM d, yyyy").create()))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(clientBuilder.build())
                    .build();
        }
        return retrofit;
    }

    private Cache getCache() {
        Cache cache = null;
        // Install an HTTP cache in the application cache directory.
        try {
            File cacheDir = new File(StorageUtils.getCacheDirectory(MyApplication.getInstance()), "http");
            cache = new Cache(cacheDir, DISK_CACHE_SIZE);
        } catch (Exception e) {
            Timber.e(e, "Unable to install disk cache.");
        }
        return cache;
    }

    public OSellService oSellService() {
        if (oSellService == null) {
            oSellService = getRetrofit().create(OSellService.class);
        }
        return oSellService;
    }
}
